/*
 * Copyright (c) 2020-2021, SERI Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-05-22     Lyons        first version
 */

module pa_fpu_xfrac_pre_shift (
    expn_diff_i,
    xfrac_i,
    xfrac_o,
    grs_o
    );

//width of xfrac is 53-bits
//include: hidden:1 + frac:52, for single adden 0s at tail

input                           expn_diff_i;
input                           xfrac_i;
output                          xfrac_o;
output                          grs_o;

wire [10:0]                     expn_diff_i;
wire [52:0]                     xfrac_i;
wire [52:0]                     xfrac_o;
wire [2:0]                      grs_o;


reg  [52:0]                     xfrac_out;
reg                             g_out;
reg                             r_out;
reg                             s_out;

wire [10:0]                     shift_cnt;
wire [52:0]                     shift_pre_data;


assign shift_cnt[10:0] = expn_diff_i[10:0];
assign shift_pre_data[52:0] = xfrac_i[52:0];

always @ (shift_cnt[10:0] or shift_pre_data[52:0]) begin
case (shift_cnt[10:0])
    11'd0   : begin
        xfrac_out[52:0] = {         shift_pre_data[52:0]};
        g_out = 1'b0;
        r_out = 1'b0;
        s_out = 1'b0;
    end
    11'd1   : begin
        xfrac_out[52:0] = {1'b0,    shift_pre_data[52:1]};
        g_out = shift_pre_data[0];
        r_out = 1'b0;
        s_out = 1'b0;
    end
    11'd2   : begin
        xfrac_out[52:0] = {2'b0,    shift_pre_data[52:2]};
        g_out = shift_pre_data[1];
        r_out = shift_pre_data[0];
        s_out = 1'b0;
    end
    11'd3   : begin
        xfrac_out[52:0] = {3'b0,    shift_pre_data[52:3]};
        g_out = shift_pre_data[2];
        r_out = shift_pre_data[1];
        s_out = shift_pre_data[0];
    end
    11'd4   : begin
        xfrac_out[52:0] = {4'b0,    shift_pre_data[52:4]};
        g_out = shift_pre_data[3];
        r_out = shift_pre_data[2];
        s_out = |shift_pre_data[1:0];
    end
    11'd5   : begin
        xfrac_out[52:0] = {5'b0,    shift_pre_data[52:5]};
        g_out = shift_pre_data[4];
        r_out = shift_pre_data[3];
        s_out = |shift_pre_data[2:0];
    end
    11'd6   : begin
        xfrac_out[52:0] = {6'b0,    shift_pre_data[52:6]};
        g_out = shift_pre_data[5];
        r_out = shift_pre_data[4];
        s_out = |shift_pre_data[3:0];
    end
    11'd7   : begin
        xfrac_out[52:0] = {7'b0,    shift_pre_data[52:7]};
        g_out = shift_pre_data[6];
        r_out = shift_pre_data[5];
        s_out = |shift_pre_data[4:0];
    end
    11'd8   : begin
        xfrac_out[52:0] = {8'b0,    shift_pre_data[52:8]};
        g_out = shift_pre_data[7];
        r_out = shift_pre_data[6];
        s_out = |shift_pre_data[5:0];
    end
    11'd9   : begin
        xfrac_out[52:0] = {9'b0,    shift_pre_data[52:9]};
        g_out = shift_pre_data[8];
        r_out = shift_pre_data[7];
        s_out = |shift_pre_data[6:0];
    end
    11'd10  : begin
        xfrac_out[52:0] = {10'b0,   shift_pre_data[52:10]};
        g_out = shift_pre_data[9];
        r_out = shift_pre_data[8];
        s_out = |shift_pre_data[7:0];
    end
    11'd11  : begin
        xfrac_out[52:0] = {11'b0,   shift_pre_data[52:11]};
        g_out = shift_pre_data[10];
        r_out = shift_pre_data[9];
        s_out = |shift_pre_data[8:0];
    end
    11'd12  : begin
        xfrac_out[52:0] = {12'b0,   shift_pre_data[52:12]};
        g_out = shift_pre_data[11];
        r_out = shift_pre_data[10];
        s_out = |shift_pre_data[9:0];
    end
    11'd13  : begin
        xfrac_out[52:0] = {13'b0,   shift_pre_data[52:13]};
        g_out = shift_pre_data[12];
        r_out = shift_pre_data[11];
        s_out = |shift_pre_data[10:0];
    end
    11'd14  : begin
        xfrac_out[52:0] = {14'b0,   shift_pre_data[52:14]};
        g_out = shift_pre_data[13];
        r_out = shift_pre_data[12];
        s_out = |shift_pre_data[11:0];
    end
    11'd15  : begin
        xfrac_out[52:0] = {15'b0,   shift_pre_data[52:15]};
        g_out = shift_pre_data[14];
        r_out = shift_pre_data[13];
        s_out = |shift_pre_data[12:0];
    end
    11'd16  : begin
        xfrac_out[52:0] = {16'b0,   shift_pre_data[52:16]};
        g_out = shift_pre_data[15];
        r_out = shift_pre_data[14];
        s_out = |shift_pre_data[13:0];
    end
    11'd17  : begin
        xfrac_out[52:0] = {17'b0,   shift_pre_data[52:17]};
        g_out = shift_pre_data[16];
        r_out = shift_pre_data[15];
        s_out = |shift_pre_data[14:0];
    end
    11'd18  : begin
        xfrac_out[52:0] = {18'b0,   shift_pre_data[52:18]};
        g_out = shift_pre_data[17];
        r_out = shift_pre_data[16];
        s_out = |shift_pre_data[15:0];
    end
    11'd19  : begin
        xfrac_out[52:0] = {19'b0,   shift_pre_data[52:19]};
        g_out = shift_pre_data[18];
        r_out = shift_pre_data[17];
        s_out = |shift_pre_data[16:0];
    end
    11'd20  : begin
        xfrac_out[52:0] = {20'b0,   shift_pre_data[52:20]};
        g_out = shift_pre_data[19];
        r_out = shift_pre_data[18];
        s_out = |shift_pre_data[17:0];
    end
    11'd21  : begin
        xfrac_out[52:0] = {21'b0,   shift_pre_data[52:21]};
        g_out = shift_pre_data[20];
        r_out = shift_pre_data[19];
        s_out = |shift_pre_data[18:0];
    end
    11'd22  : begin
        xfrac_out[52:0] = {22'b0,   shift_pre_data[52:22]};
        g_out = shift_pre_data[21];
        r_out = shift_pre_data[20];
        s_out = |shift_pre_data[19:0];
    end
    11'd23  : begin
        xfrac_out[52:0] = {23'b0,   shift_pre_data[52:23]};
        g_out = shift_pre_data[22];
        r_out = shift_pre_data[21];
        s_out = |shift_pre_data[20:0];
    end
    11'd24  : begin
        xfrac_out[52:0] = {24'b0,   shift_pre_data[52:24]};
        g_out = shift_pre_data[23];
        r_out = shift_pre_data[22];
        s_out = |shift_pre_data[21:0];
    end
    11'd25  : begin
        xfrac_out[52:0] = {25'b0,   shift_pre_data[52:25]};
        g_out = shift_pre_data[24];
        r_out = shift_pre_data[23];
        s_out = |shift_pre_data[22:0];
    end
    11'd26  : begin
        xfrac_out[52:0] = {26'b0,   shift_pre_data[52:26]};
        g_out = shift_pre_data[25];
        r_out = shift_pre_data[24];
        s_out = |shift_pre_data[23:0];
    end
    11'd27  : begin
        xfrac_out[52:0] = {27'b0,   shift_pre_data[52:27]};
        g_out = shift_pre_data[26];
        r_out = shift_pre_data[25];
        s_out = |shift_pre_data[24:0];
    end
    11'd28  : begin
        xfrac_out[52:0] = {28'b0,   shift_pre_data[52:28]};
        g_out = shift_pre_data[27];
        r_out = shift_pre_data[26];
        s_out = |shift_pre_data[25:0];
    end
    11'd29  : begin
        xfrac_out[52:0] = {29'b0,   shift_pre_data[52:29]};
        g_out = shift_pre_data[28];
        r_out = shift_pre_data[27];
        s_out = |shift_pre_data[26:0];
    end
    11'd30  : begin
        xfrac_out[52:0] = {30'b0,   shift_pre_data[52:30]};
        g_out = shift_pre_data[29];
        r_out = shift_pre_data[28];
        s_out = |shift_pre_data[27:0];
    end
    11'd31  : begin
        xfrac_out[52:0] = {31'b0,   shift_pre_data[52:31]};
        g_out = shift_pre_data[30];
        r_out = shift_pre_data[29];
        s_out = |shift_pre_data[28:0];
    end
    11'd32  : begin
        xfrac_out[52:0] = {32'b0,   shift_pre_data[52:32]};
        g_out = shift_pre_data[31];
        r_out = shift_pre_data[30];
        s_out = |shift_pre_data[29:0];
    end
    11'd33  : begin
        xfrac_out[52:0] = {33'b0,   shift_pre_data[52:33]};
        g_out = shift_pre_data[32];
        r_out = shift_pre_data[31];
        s_out = |shift_pre_data[30:0];
    end
    11'd34  : begin
        xfrac_out[52:0] = {34'b0,   shift_pre_data[52:34]};
        g_out = shift_pre_data[33];
        r_out = shift_pre_data[32];
        s_out = |shift_pre_data[31:0];
    end
    11'd35  : begin
        xfrac_out[52:0] = {35'b0,   shift_pre_data[52:35]};
        g_out = shift_pre_data[34];
        r_out = shift_pre_data[33];
        s_out = |shift_pre_data[32:0];
    end
    11'd36  : begin
        xfrac_out[52:0] = {36'b0,   shift_pre_data[52:36]};
        g_out = shift_pre_data[35];
        r_out = shift_pre_data[34];
        s_out = |shift_pre_data[33:0];
    end
    11'd37  : begin
        xfrac_out[52:0] = {37'b0,   shift_pre_data[52:37]};
        g_out = shift_pre_data[36];
        r_out = shift_pre_data[35];
        s_out = |shift_pre_data[34:0];
    end
    11'd38  : begin
        xfrac_out[52:0] = {38'b0,   shift_pre_data[52:38]};
        g_out = shift_pre_data[37];
        r_out = shift_pre_data[36];
        s_out = |shift_pre_data[35:0];
    end
    11'd39  : begin
        xfrac_out[52:0] = {39'b0,   shift_pre_data[52:39]};
        g_out = shift_pre_data[38];
        r_out = shift_pre_data[37];
        s_out = |shift_pre_data[36:0];
    end
    11'd40  : begin
        xfrac_out[52:0] = {40'b0,   shift_pre_data[52:40]};
        g_out = shift_pre_data[39];
        r_out = shift_pre_data[38];
        s_out = |shift_pre_data[37:0];
    end
    11'd41  : begin
        xfrac_out[52:0] = {41'b0,   shift_pre_data[52:41]};
        g_out = shift_pre_data[40];
        r_out = shift_pre_data[39];
        s_out = |shift_pre_data[38:0];
    end
    11'd42  : begin
        xfrac_out[52:0] = {42'b0,   shift_pre_data[52:42]};
        g_out = shift_pre_data[41];
        r_out = shift_pre_data[40];
        s_out = |shift_pre_data[39:0];
    end
    11'd43  : begin
        xfrac_out[52:0] = {43'b0,   shift_pre_data[52:43]};
        g_out = shift_pre_data[42];
        r_out = shift_pre_data[41];
        s_out = |shift_pre_data[40:0];
    end
    11'd44  : begin
        xfrac_out[52:0] = {44'b0,   shift_pre_data[52:44]};
        g_out = shift_pre_data[43];
        r_out = shift_pre_data[42];
        s_out = |shift_pre_data[41:0];
    end
    11'd45  : begin
        xfrac_out[52:0] = {45'b0,   shift_pre_data[52:45]};
        g_out = shift_pre_data[44];
        r_out = shift_pre_data[43];
        s_out = |shift_pre_data[42:0];
    end
    11'd46  : begin
        xfrac_out[52:0] = {46'b0,   shift_pre_data[52:46]};
        g_out = shift_pre_data[45];
        r_out = shift_pre_data[44];
        s_out = |shift_pre_data[43:0];
    end
    11'd47  : begin
        xfrac_out[52:0] = {47'b0,   shift_pre_data[52:47]};
        g_out = shift_pre_data[46];
        r_out = shift_pre_data[45];
        s_out = |shift_pre_data[44:0];
    end
    11'd48  : begin
        xfrac_out[52:0] = {48'b0,   shift_pre_data[52:48]};
        g_out = shift_pre_data[47];
        r_out = shift_pre_data[46];
        s_out = |shift_pre_data[45:0];
    end
    11'd49  : begin
        xfrac_out[52:0] = {49'b0,   shift_pre_data[52:49]};
        g_out = shift_pre_data[48];
        r_out = shift_pre_data[47];
        s_out = |shift_pre_data[46:0];
    end
    11'd50  : begin
        xfrac_out[52:0] = {50'b0,   shift_pre_data[52:50]};
        g_out = shift_pre_data[49];
        r_out = shift_pre_data[48];
        s_out = |shift_pre_data[47:0];
    end
    11'd51  : begin
        xfrac_out[52:0] = {51'b0,   shift_pre_data[52:51]};
        g_out = shift_pre_data[50];
        r_out = shift_pre_data[49];
        s_out = |shift_pre_data[48:0];
    end
    11'd52  : begin
        xfrac_out[52:0] = {52'b0,   shift_pre_data[52]};
        g_out = shift_pre_data[51];
        r_out = shift_pre_data[50];
        s_out = |shift_pre_data[49:0];
    end

//extra shift to create rounding grs bit
//so we can make extra 3 shift(total 53+3 shfit)

    11'd53  : begin
        xfrac_out[52:0] = {53'b0};
        g_out = shift_pre_data[52];
        r_out = shift_pre_data[51];
        s_out = |shift_pre_data[50:0];
    end
    11'd54  : begin
        xfrac_out[52:0] = {53'b0};
        g_out = 1'b0;
        r_out = shift_pre_data[52];
        s_out = |shift_pre_data[51:0];
    end
    default : begin
        xfrac_out[52:0] = {53'b0};
        g_out = 1'b0;
        r_out = 1'b0;
        s_out = |shift_pre_data[52:0];
    end
endcase
end

assign xfrac_o[52:0] = xfrac_out[52:0];

assign grs_o[2:0] = {g_out, r_out, s_out};

endmodule